﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

using System.Net;
using System.Xml;
using System.IO;
using PlayerTest.Player.Data;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading;
using PlayerTest.Player.Event;

namespace PlayerTest.Player.Handler
{
    class StudyInfoHandler
    {
        #region 변수선언
        HttpWebRequest httpWebRequest;
        HttpWebResponse httpWebResponse;

        List<InfoSentence> dic_Sentence = new List<InfoSentence>();
        List<InfoWord> dic_Word = new List<InfoWord>();
        List<InfoSection> dic_Section = new List<InfoSection>();


        List<InfoSentence> rec_Sentence = new List<InfoSentence>();
        List<InfoWord> rec_Word = new List<InfoWord>();
        List<InfoSection> rec_Section = new List<InfoSection>();

        int size_word = 0, size_sentence = 0, size_section = 0;
        #endregion

        #region Server Connection
        public string sendData(string data, string page)
        {
            httpWebRequest = (HttpWebRequest)WebRequest.Create(page);
            byte[] byteData = UTF8Encoding.UTF8.GetBytes(data);

            httpWebRequest.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
            httpWebRequest.Method = "POST";
            httpWebRequest.ContentLength = byteData.Length;

            Stream requestStream = httpWebRequest.GetRequestStream();
            requestStream.Write(byteData, 0, byteData.Length);
            requestStream.Close();

            httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
            StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream(), Encoding.GetEncoding("UTF-8"));    // Encoding.GetEncoding("EUC-KR")
            string html = streamReader.ReadToEnd();

            streamReader.Close();
            httpWebResponse.Close();

            //text.Value = html;
            return html;
        }

        /// <summary>
        /// HTTP Request 전송
        /// </summary>
        /// <param name="url"></param>
        /// <param name="nvc"></param>
        private void RequestServer(string url, NameValueCollection nvc)
        {
            try
            {
                WebClient web_client = new WebClient();
                web_client.QueryString = nvc;

                web_client.UploadValuesCompleted += new UploadValuesCompletedEventHandler(RequestCompleted);
                web_client.UploadValuesAsync(new Uri(url), nvc);
            }
            catch (WebException e)
            {
                Trace.WriteLine(String.Format("[StudyInfo] 오류발생!"));
                Trace.WriteLine(e.StackTrace);
            }
        }

        /// <summary>
        /// 비동기 HTTP Request 처리
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RequestCompleted(object sender, UploadValuesCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                String xmlresult = Encoding.UTF8.GetString(e.Result);
            }
            else
            {
                /*
                UserEventArgs arg = new UserEventArgs(UserEventArgs.eventtype.ERROR);
                arg.Result = false;
                arg.Message = "로그인 서버에 접속하는 도중 오류가 발생하였습니다!";
                SendUserEvent(arg);
                 */
            }
        }

        //video_search, subtitle_search, subtitle_download 
        public string connetServer(string key, string value, string page)
        {
            String postData = String.Format("{0}={1}", key, value);

            return sendData(postData, page);
        }

        //study_getUserData, study_getRecommendData
        public string connetServer(string key, string value, string key2, string value2, string page)
        {
            String postData = String.Format("{0}={1}&{2}={3}", key, value, key2, value2);

            return sendData(postData, page);
        }
        
        
        public string connect_Study_getUserData(string userID, string videoID)
        {
            return connetServer("user", userID, "video", videoID, "http://winz.myvnc.com/sub/Controller/study_getUserData.jsp");
        }

        //study_saveUserData
        private string connect_SendLearningInfo(string value, string value2, string value3)
        {
            String postData = String.Format("user={0}&video={1}&data={2}", value, value2, value3);

            return sendData(postData, "http://winz.myvnc.com/sub/Controller/study_saveUserData.jsp");
        }
        #endregion

        #region Event Sending
        public event StudyInfoEventHandler EventHandler;
        /// <summary>
        /// Controller에 메시지 전송
        /// </summary>
        /// <param name="arg"></param>
        private void SendStudyInfoEvent(StudyInfoEventArgs arg)
        {
            // 연결된 모든 함수에 이벤트 전송
            StudyInfoEventHandler handler = EventHandler;
            if (handler != null) handler(this, arg);
        }
        #endregion

        #region StudyInfo 받기
        /// <summary>
        /// 자신의 학습 StudyInfo를 받아옵니다.
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="videoID"></param>
        public bool RequestMyStudyInfo(int userID, int videoID)
        {
            dic_Section.Clear();
            dic_Sentence.Clear();
            dic_Word.Clear();
            return RequestStudyInfo(userID, videoID, "study_getUserData.jsp");
        }

        /// <summary>
        /// 해당 영상의 추천 StudyInfo를 받아옵니다.
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="videoID"></param>
        public bool RequestRecommendStudyInfo(int userID, int videoID)
        {
            rec_Section.Clear();
            rec_Sentence.Clear();
            rec_Word.Clear();
            return RequestStudyInfo(userID, videoID, "study_getRecommendData.jsp");
        }

        public void RequestImageDownload()
        {
            CancellationTokenSource cts = new CancellationTokenSource();
            Task downloadTask = Task.Factory.StartNew(() =>
            {
                try
                {
                    //비동기로 다운로드 작업을 시작
                    WebClient client = new WebClient();

                    for (int i = 0; i < dic_Section.Count; i++)
                    {
                        string filename = dic_Section[i].Thumb;
                        string url = string.Format("http://winz.myvnc.com/sub/Files/Thumbs/{0}", filename);
                        string filePath
                            = string.Format("{0}\\thumbs\\{1}", Environment.CurrentDirectory, filename);

                        System.IO.File.Delete(filePath);
                        client.DownloadFile(url, filePath);
                    }
                    
                    for (int i = 0; i < rec_Section.Count; i++)
                    {
                        string filename = rec_Section[i].Thumb;
                        string url = string.Format("http://winz.myvnc.com/sub/Files/Thumbs/{0}", filename);
                        string filePath
                            = string.Format("{0}\\thumbs\\{1}", Environment.CurrentDirectory, filename);

                        System.IO.File.Delete(filePath);
                        client.DownloadFile(url, filePath);
                    }
                }
                catch (Exception e)
                {
                    throw;
                }
            }, cts.Token);

            downloadTask.Wait();
            SendStudyInfoEvent(new StudyInfoEventArgs(StudyInfoEventArgs.eventtype.DOWNFINISH));
        }

        public void SaveStudyInfo(int userid, int videoid)
        {
            string xml = ToXML();
            string uid = Convert.ToString(userid);
            string vid = Convert.ToString(videoid);

            if (xml.Length > 0)
            {
                //서버에 학습데이터 보내기
                xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><UserData>" + xml + "</UserData>";
                Trace.WriteLine(xml);
                Trace.WriteLine(connect_SendLearningInfo(uid, vid, xml));
            }
        }

        private string ToXML()
        {
            string result = "";
            string learningInfo = "";

            if (dic_Sentence.Count != 0)
            {
                learningInfo = "<Sentence>";

                foreach (InfoSentence sentence in dic_Sentence)
                    learningInfo = learningInfo + String.Format("<Item position=\"{0}\">{1}</Item>", sentence.Start, sentence.Sent);

                learningInfo = learningInfo + "</Sentence>";
                result += learningInfo;
            }
            

            if (dic_Word.Count != 0)
            {
                learningInfo = "<Word>";

                foreach (InfoWord word in dic_Word)
                    learningInfo = learningInfo + String.Format("<Item>{0}</Item>", word.Word);

                learningInfo = learningInfo + "</Word>";
                result += learningInfo;
            }
            /*
            if (dic_Section.Count != 0)
            {
                learningInfo = "<Section>";
                int start;
                int end;

                foreach (InfoSection section in dic_Section)
                {
                    start = Convert.ToInt32(section.Start * 1000.0);
                    end = Convert.ToInt32(section.End * 1000.0);
                    learningInfo = learningInfo + String.Format("<Item start=\"{0}\" end=\"{1}\">{2}</Item>", start, end, section.Thumb);
                }
                learningInfo = learningInfo + "</Section>";
                result += learningInfo;
            }
             */
            return result;
        }

        /// <summary>
        /// 자신의 학습 StudyInfo나 추천 StudyInfo를 받아옵니다.
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="videoID"></param>
        /// <param name="page"></param>
        private bool RequestStudyInfo(int userID, int videoID, string page)
        {
            string word = null;
            long position = 0;
            string sentence = null;
            int start = 0;
            int end = 0;
            string thumb = null;

            bool isWord = false;
            bool isSentence = false;
            bool isSection = false;

            bool isRecommendData = false;

            string Url = "http://winz.myvnc.com/sub/Controller/" + page;
            Url = String.Format(Url + "?user={0}&video={1}", userID, videoID);
            XmlTextReader xmlReader = new XmlTextReader(Url);

            if (page.Contains("Recommend"))
            {
                isRecommendData = true;
            }
            else
            {
                isRecommendData = false;
            }


            while (xmlReader.Read())
            {
                switch (xmlReader.LocalName)
                {
                    case "Word":
                        isWord = true;
                        isSentence = false;
                        isSection = false;
                        break;

                    case "Sentence":
                        isWord = false;
                        isSentence = true;
                        isSection = false;
                        break;

                    case "Section":
                        isWord = false;
                        isSentence = false;
                        isSection = true;
                        break;

                    case "Item":
                        if (isWord)
                        {
                            word = xmlReader.ReadElementContentAsString();
                            if (!isRecommendData)
                                dic_Word.Add(new InfoWord(word));
                            else
                                rec_Word.Add(new InfoWord(word));
                            size_word++;
                        }

                        else if (isSentence)
                        {
                            position = long.Parse(xmlReader.GetAttribute(0));
                            sentence = xmlReader.ReadElementContentAsString();

                            if (!isRecommendData)
                                dic_Sentence.Add(new InfoSentence(position, sentence));
                            else
                                rec_Sentence.Add(new InfoSentence(position, sentence));

                            size_sentence++;
                        }

                        else if (isSection)
                        {
                            start = int.Parse(xmlReader.GetAttribute("start"));
                            end = int.Parse(xmlReader.GetAttribute("end"));
                            thumb = xmlReader.GetAttribute("thumb");

                            //size_section
                            if (!isRecommendData)
                                dic_Section.Add(new InfoSection(start, end, thumb));
                            else
                                rec_Section.Add(new InfoSection(start, end, thumb));

                            size_section++;
                        }

                        break;
                }
            } // while

            return true;
        } //method End!
        #endregion

        #region Input / Output
        public void InsertMySection(InfoSection section)
        {
            // size_section
            dic_Section.Add(section);
        }
        #endregion

        #region Properties
        public List<InfoWord> MyWord
        {
            get { return dic_Word; }
            set { dic_Word = value; }
        }

        public List<InfoSentence> MySentence
        {
            get { return dic_Sentence; }
            set { dic_Sentence = value; }
        }

        public List<InfoSection> MySection
        {
            get { return dic_Section; }
            set { dic_Section = value; }
        }

        public List<InfoWord> RecommendWord
        {
            get { return rec_Word; }
            set { rec_Word = value; }
        }

        public List<InfoSentence> RecommendSectence
        {
            get { return rec_Sentence; }
            set { rec_Sentence = value; }
        }

        public List<InfoSection> RecommendSection
        {
            get { return rec_Section; }
            set { rec_Section = value; }
        }

        public int SIZE_WORD
        {
            get { return size_word; }
            set { size_word = value; }
        }

        public int SIZE_SENTENCE
        {
            get { return size_sentence; }
            set { size_sentence = value; }
        }

        public int SIZE_SECTION
        {
            get { return size_section; }
            set { size_section = value; }
        }
        #endregion
    }
}